package com.wd.command;

import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.helpers.LogLog;

import com.wd.entity.user.UserInfoEntity;
import com.wd.nio.DataPacket;
import com.wd.nio.SessionObject;

/**
 * @author long
 * @Create 2012-10-11 下午5:34:55
 * @QQ 108232706
 * @version 1.0
 * @description BaseCommandObject
 */
public class BaseCommandObject implements Comparable<BaseCommandObject> {

	private short cmd;
	private int cmdstatus;
	byte type;
	public int dbIndex;
	public String name;// 标识
	public long runTime;// 当前入队列时间是纳秒
	public long initialDelay;// 开始执行时间，一个命令的执行时间为initialDelay,initialDelay+1*period+delay
	public long period;// 延时
	public int totalCount;// 总共执行的次数，-1无限次，1只一次，0，不执行
	public int currentCount;// 当前执行的次数
	public TimeUnit unit;// 时间单位
	/**
	 * 是否取消，对于在执行中的任务没有办法在队列取消，只能给个取消状态，使得线程不回收，直接扔弃
	 */
	private boolean isCancel = false;

	public DataPacket dataPacket;
	// private final ByteBuffer bytes;
	public SessionObject sessionObject;

	// ================================SessionObject===========
	public int getStatus() {
		return sessionObject.getStatus();

	}

	/**
	 * 设置sessioObject的状态，1-5
	 * 
	 * @param status
	 */
	public void setStatus(int status) {
		sessionObject.setStatus(status);
	}

	/**
	 * 设置sessioObject的状态，1-5
	 * 
	 * @param status
	 */
	public void setCmdStatus(int index, byte status) {
		sessionObject.cmdStatus[index] = status;
	}

	public void setUser(UserInfoEntity user) {
		sessionObject.setUser(user);

	}

	public UserInfoEntity getUser() {
		return sessionObject.getUser();

	}

	public ByteBuffer getBytes() {
		return dataPacket.byteBuffer;
	}

	public void setCmd(short cmd) {
		this.cmd = cmd;
		if (this.dataPacket != null)
			this.dataPacket.cmdId = cmd;
	}

	// 写操作
	// public ByteBuffer wrap(byte[] bytes) {
	//
	// return dataPacket.wrap(bytes);
	// }
	//
	// public ByteBuffer wrap(String msg) {
	// return dataPacket.wrap(msg);
	// }

	public void writeBegin() {
		dataPacket.writeBegin();
	}

	// public void writeBegin(int size) {
	// dataPacket.writeBegin(size);
	// }

	public void writeByte(byte value) {
		dataPacket.writeByte(value);
	}

	public void writeBytes(byte[] bytes) {
		dataPacket.writeBytes(bytes);
	}

	public void putBytes(byte[] bytes) {
		dataPacket.putBytes(bytes);
	}

	public void writeShort(Short value) {
		dataPacket.writeShort(value);
	}

	public void writeInt(int value) {
		dataPacket.writeInt(value);
	}

	public void writeFloat(float value) {
		dataPacket.writeFloat(value);
	}

	public void writeString(String msg) {
		dataPacket.writeString(msg);
	}

	public void writeEnd() {
		dataPacket.flip();
	}

	// 读取操作

	public char readChar() {
		return dataPacket.readChar();
	}

	public byte readByte() {
		return dataPacket.readByte();
	}

	public void readBytes(byte[] dst, int offset, int length) {
		dataPacket.readBytes(dst, offset, length);
	}

	public float readFloat() {
		return dataPacket.readFloat();
	}

	public long readLong() {
		return dataPacket.readLong();
	}

	public double readDouble() {
		return dataPacket.readDouble();
	}

	public int readInt() {
		return dataPacket.readInt();
	}

	public short readShort() {
		return dataPacket.readShort();
	}

	public String readString() {
		return dataPacket.readString();
	}

	public ByteBuffer pack() {
		int l = length();
		ByteBuffer byteBufferer = ByteBuffer.allocate(l);
		if (position() > 0) {
			flip();
		}
		byteBufferer.put(array(), 0, l);
		byteBufferer.flip();
		return byteBufferer;
	}

	public byte[] array() {
		return dataPacket.array();
	}

	public int position() {
		return dataPacket.position();
	}

	public void position(int newPosition) {
		dataPacket.position(newPosition);
	}

	public int remaining() {
		return dataPacket.remaining();
	}

	public int limit() {
		return dataPacket.limit();
	}

	public void flip() {
		dataPacket.flip();
	}

	public void clear() {
		dataPacket.clear();
	}

	/**
	 * 
	 * @return
	 */
	public int length() {
		return dataPacket.length();
	}

	/**
	 * 
	 * 
	 * @return
	 */
	public int totalSize() {
		return dataPacket.totalSize();
	}

	public void outInfo(byte[] bytes) {
		dataPacket.outInfo(bytes);
	}

	// ================================处理显示，打印，所有的操作不改变position===========

	/**
	 * 将数据以16进制展现
	 * 
	 * @return
	 */
	public String byteToHex() {
		return dataPacket.byteToHex();
	}

	/**
	 * 每字节的数值
	 * 
	 * @return
	 */
	public String byteToString() {
		return dataPacket.byteToString();
	}

	public String decodeToString() {
		return dataPacket.decodeToString();
	}

	public BaseCommandObject(DataPacket _dataPacket, UserInfoEntity user) {
		this.dataPacket = _dataPacket;
		this.sessionObject = new SessionObject(null,user);
//		this.setUser(user);
		if (dataPacket != null) {
			this.setCmd(this.dataPacket.cmdId);
		}
	}

	public BaseCommandObject(SessionObject _sessionObject, DataPacket _dataPacket) {
		this.sessionObject = _sessionObject;
		this.dataPacket = _dataPacket;
		this.dbIndex = -1;
		if (dataPacket != null) {
			this.setCmd(this.dataPacket.cmdId);
		}
	}

	/**
	 * 周期性间隔执行的命令
	 * 
	 * @param _initialDelay
	 * @param _period
	 * @param _totalCount
	 */
	public BaseCommandObject(long _initialDelay, long _period, int _totalCount) {
		if (_initialDelay < 0 || (_totalCount != 1 && _period <= 0) || (_totalCount < 1 && _totalCount != -1)) {
			throw new IllegalArgumentException("BaseCommand arguement error!");
		}
		initialDelay = _initialDelay;
		period = _period;
		totalCount = _totalCount;
		unit = TimeUnit.MILLISECONDS;
		// this.dataPacket=new DataPacket(10*1024);
	}

	public BaseCommandObject(String _name, long _initialDelay, long _period, int _totalCount) {
		this(_initialDelay, _period, _totalCount);
		this.name = _name;
	}

	public BaseCommandObject(String _name, long _initialDelay, long _period, int _totalCount, TimeUnit _unit) {
		this(_initialDelay, _period, _totalCount);
		this.name = _name;
		unit = _unit;
	}

	/**
	 * 立即执行一次
	 */
	public BaseCommandObject() {
		this.dataPacket = new DataPacket(10 * 1024);
	}

	/**
	 * 执行一次的命令
	 * 
	 * @param delay
	 */
	public BaseCommandObject(long delay) {
		this(delay, 0, 1);
	}

	public BaseCommandObject(long delay, TimeUnit _unit) {
		this(delay, 0, 1);
		unit = _unit;
	}

	public void delay(long delay, TimeUnit _unit) {
		initialDelay = delay;
		unit = _unit;
	}

	public void start() {
		reset();
		runTime = System.nanoTime() + TimeUnit.NANOSECONDS.convert(initialDelay, unit);
	}

	public int getLeftTime() {
		return (int) getLeftTime(TimeUnit.SECONDS);
	}

	public long getLeftTime(TimeUnit unit) {
		long left = runTime - System.nanoTime();
		return unit.convert(left, TimeUnit.NANOSECONDS);
	}

	private void reset() {
		this.currentCount = 1;
	}

	/**
	 * 命令执行完一次，时间加延时，并告诉外面，是否命令执行完毕,若没有执行完，继续入栈优先级队列
	 * 
	 * @return
	 */
	public boolean complete() {
		if (isCancel())
			return true;
		currentCount++;
		runTime += TimeUnit.NANOSECONDS.convert(period, unit);
		if (totalCount == -1)// -1标示是个无限次任务
		{
//			Log.debug(this.name + ",无限循环任务,间隔," + this.period + " " + this.unit);
			return false;
		}
		if (currentCount >= totalCount)// 执行次数大于=总次数,执行完毕
			return true;
		return false;// 上面的差集就是未完成
	}

	public short getCmd() {
		return cmd;
	}

	// public void setCmd(short cmd) {
	// this.cmd = cmd;
	// }

	public int getCmdstatus() {
		return cmdstatus;
	}

	public void setCmdstatus(int cmdstatus) {
		this.cmdstatus = cmdstatus;
	}

	public int compareTo(BaseCommandObject o) {
		if (o instanceof BaseCommandObject) {
			return runTime > o.runTime ? 1 : -1;
		}
		return 0;
	}

	@Override
	public String toString() {
		return String.format("当前命令信息：cmd:%s name:%s dbIndex:%s runTime:%s  initialDelay:%s period:%s totalCount:%s currentCount:%s unit:%s]", cmd, name, dbIndex, runTime, initialDelay, period, totalCount, currentCount, unit);
	}

	public boolean isCancel() {
		return isCancel;
	}

	public void setCancel(boolean isCancel) {
		this.isCancel = isCancel;
		if (this.isCancel) {
			LogLog.warn(this.name + "任务状态被取消");
		}
	}
}
